home *** CD-ROM | disk | FTP | other *** search
- /* DTMF.C */
- /* Author: Emil LAURENTIU */
- /* Last modified: Tuesday, 05 August 1997 */
-
- #include <stdio.h>
- #include <conio.h>
- #include <dos.h>
- #include <string.h>
-
- #include "freq.h"
-
- extern char matrix_dtmf[4][4];
- extern int f_dtmf[];
- extern double f_ctcss[];
- extern int sb_f_dtmf[];
- extern int dtmf_delay;
- extern int sb_addr;
-
- static unsigned ticking = 0;
-
- static FM_Instrument instrument = {
- 0x3f, 0x3f, /* Level */
- 0x00, 0x00, /* Multiple */
- 0x00, 0x00, /* Attack */
- 0x00, 0x00, /* Decay */
- 0x0f, 0x0f, /* Sustain */
- 0x00, 0x00, /* Release */
- 0x00, 0x00, /* WaveSelect */
- 0x00, 0x00, /* Amp_Vib_EnvG */
- 0x01, 0x00 /* Algorithm, Feedback */
- };
- int notes[12] = {0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5,
- 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE};
-
- /* dtmf.c 05/08/97 23.37.34 */
- unsigned char op_p( int voice, int op );
- void Sb_FM_Reset( void );
- void Sb_FM_Key_Off( int voice );
- void Sb_FM_Key_On( int voice, int freq, int octave );
- void Sb_FM_Voice_Volume( int voice, int op, int vol );
- void Sb_FM_Voice_At_De( int voice, int op, int atack, int decay );
- void Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release );
- void Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple );
- void Sb_FM_Voice_WaveSelect( int voice, int op, int wave );
- void Sb_FM_Voice_FeedBack( int voice, int type, int strength );
- void Sb_FM_Set_Voice( int voice, FM_Instrument * ins );
- void interrupt new_timer( void );
- unsigned long timer_hiticks( void );
- void delay_loop( int time );
- void generate_DTMF( char *nr );
- double generate_CTCSS( int gen_ctcss );
-
- static void
- WriteFM( int addr, unsigned char data )
- {
- int i;
-
- /* Left Channel */
- outportb( sb_addr + 0, addr );
- for ( i = 0; i < 6; i++ )
- inportb( sb_addr + 0 );
- outportb( sb_addr + 1, data );
- for ( i = 0; i < 35; i++ )
- inportb( sb_addr + 0 );
- /* Rigth Channel */
- outportb( sb_addr + 2, addr );
- for ( i = 0; i < 6; i++ )
- inportb( sb_addr + 2 );
- outportb( sb_addr + 3, data );
- for ( i = 0; i < 35; i++ )
- inportb( sb_addr + 2 );
- }
-
- unsigned char
- op_p( int voice, int op )
- {
- unsigned char c;
-
- c = ( --voice ) % 9;
- c = ( c / 3 ) << 3 | c % 3;
- c += 3 * ( ( --op ) & 1 );
- return ( c );
- }
-
- void
- Sb_FM_Reset( void )
- {
- int i;
-
- WriteFM( 1, 0x20 ); /* FM waveform */
- WriteFM( 4, 0 ); /* disable timers */
- WriteFM( 8, 0 ); /* select FM music mode */
- WriteFM( 0xbd, 0xc0 ); /* no drums */
- for ( i = 1; i <= 9; i++ )
- {
- Sb_FM_Key_Off( i );
- Sb_FM_Voice_WaveSelect( i, 1, 0 );
- Sb_FM_Voice_WaveSelect( i, 2, 0 );
- }
- }
-
- void
- Sb_FM_Key_Off( int voice )
- {
- WriteFM( 0xB0 + ( --voice ) % 9, 0 ); /* turn voice off */
- }
-
- void
- Sb_FM_Key_On( int voice, int freq, int octave )
- {
- --voice;
- voice %= 9;
- WriteFM( 0xb0 + voice, 0 );
- WriteFM( 0xa0 + voice, freq & 0xff );
- WriteFM( 0xb0 + voice, ( freq >> 8 ) | ( octave << 2 ) | 0x20 );
- }
-
- void
- Sb_FM_Voice_Volume( int voice, int op, int vol )
- {
- WriteFM( 0x40 + op_p( voice, op ), ~vol & 0x3f | 0x40 );
- }
-
- void
- Sb_FM_Voice_At_De( int voice, int op, int atack, int decay )
- {
- WriteFM( 0x60 + op_p( voice, op ), ( ~atack & 0xf ) << 4 | decay & 0xf );
- }
-
- void
- Sb_FM_Voice_Su_Re( int voice, int op, int sustain, int release )
- {
- WriteFM( 0x80 + op_p( voice, op ), ( sustain & 0xf ) << 4 | ~release & 0xf );
- }
-
- void
- Sb_FM_Voice_Character( int voice, int op, int amp_vib_envg, int multiple )
- {
- WriteFM( 0x20 + op_p( voice, op ), ( amp_vib_envg & 7 ) << 5 | ( multiple + 1 ) & 0xf );
- }
-
- void
- Sb_FM_Voice_WaveSelect( int voice, int op, int wave )
- {
- WriteFM( 0xe0 + op_p( voice, op ), wave & 3 );
- }
-
- void
- Sb_FM_Voice_FeedBack( int voice, int type, int strength )
- {
- WriteFM( 0xc0 + ( --voice ) % 9, ( strength & 7 ) << 1 | type & 1 );
- }
-
- void
- Sb_FM_Set_Voice( int voice, FM_Instrument * ins )
- {
- int op;
-
- for ( op = 1; op <= 2; op++ )
- {
- Sb_FM_Voice_Volume( voice, op, ins->Level[op - 1] );
- Sb_FM_Voice_At_De( voice, op, ins->Atack[op - 1], ins->Decay[op - 1] );
- Sb_FM_Voice_Su_Re( voice, op, ins->Sustain[op - 1], ins->Release[op - 1] );
- Sb_FM_Voice_Character( voice, op, ins->Amp_Vib_EnvG[op - 1], ins->Multiple[op - 1] );
- Sb_FM_Voice_WaveSelect( voice, op, ins->WaveSelect[op - 1] );
- }
- Sb_FM_Voice_FeedBack( voice, ins->Algorithm, ins->Feedback );
- }
-
- void interrupt
- new_timer( )
- {
- ticking++;
- outportb( 0x20, 0x20 ); /* Send EOI */
- }
-
-
- unsigned long
- timer_hiticks( )
- {
- outportb( 0x43, 0x00 ); /* Send latch command to 8253 counter 0 */
- return ( ( unsigned long ) ticking << 16 ) |
- ( unsigned ) -( inportb( 0x40 ) | ( inportb( 0x40 ) << 8 ) );
- }
-
- void
- delay_loop( int time ) /* Delay is in milisecond increments */
- {
- unsigned long val;
-
- val = timer_hiticks( ) + 1193L * time;
- while ( val > timer_hiticks( ) ); /* Wait */
- }
-
- void
- generate_DTMF( char *nr )
- {
- int i, j;
- int xoff = WINDOW_LEFT;
- char nc;
- int key;
- void interrupt( *old_int ) ( );
-
- disable( );
- old_int = getvect( 8 ); /* timer */
- setvect( 8, new_timer );
- enable( );
-
- Sb_FM_Set_Voice( 1, &instrument );
- Sb_FM_Set_Voice( 2, &instrument );
- Sb_FM_Voice_Volume( 1, 1, 0x3f );
- Sb_FM_Voice_Volume( 2, 1, 0x3f );
- Sb_FM_Voice_Volume( 1, 2, 0x3f );
- Sb_FM_Voice_Volume( 2, 2, 0x3f );
- while ( *nr )
- {
- key = 0;
- for ( i = 0; i < 4; i++ )
- for ( j = 0; j < 4; j++ )
- if ( matrix_dtmf[i][j] == *nr )
- {
- key++;
- Sb_FM_Key_On( 1, sb_f_dtmf[i], 5 );
- Sb_FM_Key_On( 2, sb_f_dtmf[j + 4], 6 );
- }
- nc = *( nr + 1 );
- *( nr + 1 ) = 0;
- draw_text_left( xoff, MGY, nr );
- xoff += 8;
- *( nr + 1 ) = nc;
- if ( key )
- delay_loop( dtmf_delay << 1 );
- Sb_FM_Key_Off( 1 );
- Sb_FM_Key_Off( 2 );
- if ( !key )
- delay_loop( dtmf_delay << 1 );
- delay_loop( dtmf_delay );
- nr++;
- }
- Sb_FM_Voice_Volume( 1, 1, 0 );
- Sb_FM_Voice_Volume( 2, 1, 0 );
- Sb_FM_Voice_Volume( 1, 2, 0 );
- Sb_FM_Voice_Volume( 2, 2, 0 );
-
- disable( );
- setvect( 8, old_int );
- enable( );
- }
-
- double
- generate_CTCSS( int gen_ctcss )
- {
- double err = 0;
- const double step = 1e5 / 2097152;
- int factor, multiply;
-
- if ( gen_ctcss == CTCSS_MAX )
- Sb_FM_Key_Off( 3 );
- else
- {
- Sb_FM_Set_Voice( 3, &instrument );
- multiply = f_ctcss[gen_ctcss] / step / 1024;
- multiply++;
- WriteFM( 0x20 + op_p( 3, 1 ), multiply ); /* use freq * multiply */
- WriteFM( 0x20 + op_p( 3, 2 ), multiply ); /* for better resolution */
- factor = f_ctcss[gen_ctcss] / step / multiply + 0.5;
- err = step * factor * multiply - f_ctcss[gen_ctcss];
- Sb_FM_Key_On( 3, factor, 0 ); /* use ocatave 0 */
- WriteFM( 0x40 + op_p( 3, 1 ), 0xC0 ); /* maximum volume (0x3F) */
- WriteFM( 0x40 + op_p( 3, 2 ), 0xC0 ); /* 6 db/octave decrease */
- }
- return ( err );
- }
-